﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Windows.Forms;

namespace SIA.Messages
{
    /// <summary> Tipo di Messaggio Attualmente solo gli warning e gli errori fanno apparire la message box </summary>
    public enum eMessageType
	{
	    DEBUG, INFO, WARNING, ERROR, EVENT, JOB
	}  

    /// <summary>Struttura di un Messaggio contenente la sorgente il messaggio e la data di aquisizione</summary>
    public struct Message
	{
        public Object Sender;
	    public String Text;        
        public eMessageType MessageType;
        public DateTime AquiredDateTime;

        public Message(Object sender, String text, eMessageType messageType)
        {
            this.Sender = sender;
            this.Text = text;
            this.MessageType = messageType;
            this.AquiredDateTime = DateTime.Now;
        }

        public bool Equals(Message m)
        {
            return ((Sender==null && m.Sender==null) || Sender.Equals(m.Sender)) && Text.Equals(m.Text) && AquiredDateTime.Equals(m.AquiredDateTime);
        }

        public override string ToString()
        {
            return "<" + this.AquiredDateTime.ToString("yyyy-MM-dd HH:mm:ss") + " - " + this.MessageType.ToString() + "> " + this.Text + " (from:" + this.Sender + ")"; 
        }

	}
    /// <summary>Evento Generico per un messaggio</summary>
    /// <param name="message"></param>
    public delegate void MessageEvent(Message message);
    
    /// <summary>Classe Statica per la Gestione Dei Messaggi</summary>
    public static class MessageManager
    {
        public const int CAPACITY = 4096;

        private static List<Message> _messageList = new List<Message>(CAPACITY);
        private static Boolean _showMessageBox = true;
        private static Boolean _writeToFile = true;
        private static String _fileFullName = ".." + System.IO.Path.DirectorySeparatorChar + "var" + System.IO.Path.DirectorySeparatorChar + "log" + System.IO.Path.DirectorySeparatorChar + "message.txt";

        /// <summary>Evento Nuovo messaggio lanciato in un nuovo thread</summary>
        public static event MessageEvent NewMessage;

        public static Message LastMessage { get {
            if (_messageList.Count > 0)
                return _messageList.Last();
            else
                return new Message(null,"The list message is empty",eMessageType.INFO);
        } }
        public static Boolean WriteToFile { get { return _writeToFile; } set { _writeToFile = value; } }
        public static Boolean ShowMessageBox { get { return _showMessageBox; } set { _showMessageBox = value; } }


        static MessageManager()
        {
            sendMessage(null, "Message Manager Start", eMessageType.INFO);
        }

        /// <summary>Invio di un Eccezione</summary>
        /// <param name="sender"></param>
        /// <param name="ex"></param>
        public static void sendMessage(Object sender, String text, Exception ex)
        { sendMessage(sender, text + ": " + ex.Message, eMessageType.WARNING, _showMessageBox); }

        /// <summary>Invio di un nuovo messaggio </summary>
        /// <param name="sender"></param>
        /// <param name="text"></param>
        /// <param name="messageType"></param>
        public static void sendMessage(Object sender, String text, eMessageType messageType)
            { sendMessage(sender, text, messageType, _showMessageBox); }

        /// <summary>Invio di un nuovo messaggio </summary>
        /// <param name="sender"></param>
        /// <param name="text"></param>
        /// <param name="messageType"></param>
        /// <param name="showMessageBox"></param>
        public static void sendMessage(Object sender, String text, eMessageType messageType, Boolean showMessageBox)
        {
            //Creazione del messaggio
            Message message = new Message(sender, text, messageType);

            //Prevengo il doppio messaggio
            if (!message.Equals(LastMessage))
            {
                //Se la lista e' troppo grande la sostituisco con una nuova
                if (_messageList.Count > CAPACITY)
                    _messageList = new List<Message>(CAPACITY);

                //Memorizza il Messaggio
                _messageList.Add(message);

                //Send Event
                if (NewMessage != null)
                    new Thread(new ThreadStart(delegate { NewMessage(message); })).Start();

                //Show Message Box
                if (showMessageBox == true)
                    if (message.MessageType == eMessageType.ERROR || message.MessageType == eMessageType.WARNING)
                        MessageBox.Show(message.ToString());

                //Write To File
                if (_writeToFile == true)
                {
                    lock (_fileFullName)
                    {
                        TextWriter tw = new StreamWriter(_fileFullName, true);  // create a writer and open the file                
                        tw.WriteLine(message.ToString());                       // write a line of text to the file                
                        tw.Close();                                             // close the stream
                    }

                }
            }
        }

    }
}
